﻿using System.Collections.Generic;
using UnityEngine;


namespace Share
{

    /// <summary>
    /// 用于统计和管理游戏性能分析数据的类
    /// </summary>
    public class ProfilerData
    {
        /// <summary>
        /// 总开关
        /// 为false，则不会显示ui
        /// </summary>
        public static bool EnableProfilerSwitch = true;

        /// <summary>
        /// 是否统计文件（如lua和csv）的内存使用
        /// </summary>
        public const bool EnableFileProfile = false;

        /// <summary>
        /// 是否正在统计信息
        /// </summary>
        public static bool IsProfiling = false;

        /// <summary>
        /// 获取是否需要统计或显示分析数据的标志
        /// </summary>
        /// <returns></returns>
        public static bool Flag
        {
            get
            {
                return EnableProfilerSwitch || EnableFileProfile;
            }
        }

        /// <summary>
        /// KB单位的换算常量
        /// </summary>
        public const float K_ = 1024f;
        /// <summary>
        /// MB单位的换算常量
        /// </summary>
        public const float M_ = K_ * K_;

        /// <summary>
        /// 存储lua文件名和其对应内存大小的字典
        /// </summary>
        static readonly Dictionary<string, float> luaSrcDict = new Dictionary<string, float>();
        /// <summary>
        /// 存储lua文件名的集合，用于快速查找
        /// </summary>
        static readonly HashSet<string> luaNameSet = new HashSet<string>();
        /// <summary>
        /// 存储csv文件名和其对应内存大小的字典
        /// </summary>
        static readonly Dictionary<string, float> csvDict = new Dictionary<string, float>();
        /// <summary>
        /// 存储csv文件名的集合，用于快速查找
        /// </summary>
        static readonly HashSet<string> csvNameSet = new HashSet<string>();

        /// <summary>
        /// 添加lua文件并统计其内存使用
        /// </summary>
        /// <param name="name">文件名</param>
        /// <param name="ta">TextAsset对象</param>
        public static void AddLuaFile(string name, TextAsset ta)
        {
            if (ta == null)
            {
                return;
            }
            luaNameSet.Add(ta.name.ToLower());

            if (!Flag)
            {
                return;
            }
            else
            {
                //if (!Profiler.enabled)
                //{
                //    Profiler.enabled = true;
                //}
            }

            var size = UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(ta);
            luaSrcDict[name] = size / M_;
        }

        /// <summary>
        /// 添加csv文件并统计其内存使用
        /// </summary>
        /// <param name="name">文件名</param>
        /// <param name="ta">TextAsset对象</param>
        public static void AddCSVFile(string name, TextAsset ta)
        {
            if (ta == null)
            {
                return;
            }
            csvNameSet.Add(ta.name.ToLower());

            if (!Flag)
            {
                return;
            }
            else
            {
                //if (!Profiler.enabled)
                //{
                //    Profiler.enabled = true;
                //}
            }

            var size = UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(ta);
            csvDict[name] = size / M_;
        }

        /// <summary>
        /// 检查csv文件是否已加载
        /// </summary>
        /// <param name="name">文件名</param>
        /// <returns>如果已加载返回true，否则返回false</returns>
        public static bool IsCSV(string name)
        {
            return csvNameSet.Contains(name.ToLower());
        }

        /// <summary>
        /// 检查lua文件是否已加载
        /// </summary>
        /// <param name="name">文件名</param>
        /// <returns>如果已加载返回true，否则返回false</returns>
        public static bool IsLua(string name)
        {
            return luaNameSet.Contains(name.ToLower());
        }

        /// <summary>
        /// 存储分析结果的类
        /// </summary>
        public class Result
        {
            /// <summary>
            /// 对象数量
            /// </summary>
            public int count;
            /// <summary>
            /// 内存大小（以MB为单位）
            /// </summary>
            public float MB;
        }

        /// <summary>
        /// 统计GameObject的内存使用
        /// </summary>
        /// <returns>包含GameObject数量和总内存大小的结果对象</returns>
        public static Result GetMem_GameObject()
        {
            Result r = new Result();
            GameObject[] textures = Object.FindObjectsOfType(typeof(GameObject)) as GameObject[];
            r.count = textures.Length;

            long size = 0;
            foreach (GameObject t in textures)
            {
                if (!string.IsNullOrEmpty(t.name))
                {
                    size += UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(t);
                }
            }
            r.MB = (float)size / M_;
            return r;
        }

        /// <summary>
        /// 根据类型统计内存使用
        /// </summary>
        /// <param name="check">检查对象是否应被统计的委托</param>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns>包含对象数量和总内存大小的结果对象</returns>
        public static Result GetMemByType<T>(System.Func<T, bool> check)
        {
            Result r = new Result();

            T[] objs = Resources.FindObjectsOfTypeAll(typeof(T)) as T[];
            long size = 0;
            foreach (var i in objs)
            {
                bool flag = true;
                if (check != null)
                {
                    flag = check(i);
                }

                if (flag)
                {
                    r.count++;
                    size += UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(i as Object);
                }
            }
            r.MB = (float)size / M_;

            return r;
        }

        /// <summary>
        /// 获取全部内存使用
        /// </summary>
        /// <returns>总内存大小（以MB为单位）</returns>
        public static float GetTotalMem()
        {
            var total = (float)UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong();
            total /= M_;
            return total;
        }

        /// <summary>
        /// 获取未使用的内存
        /// </summary>
        /// <returns>未使用内存大小（以MB为单位）</returns>
        public static float GetUnusedMem()
        {
            var total = (float)UnityEngine.Profiling.Profiler.GetTotalUnusedReservedMemoryLong();
            total /= M_;
            return total;
        }

        /// <summary>
        /// 获取Mono堆的大小
        /// </summary>
        /// <returns>Mono堆大小（以MB为单位）</returns>
        public static float GetMonoHeapMem()
        {
            var total = (float)UnityEngine.Profiling.Profiler.GetMonoHeapSizeLong();
            total /= M_;
            return total;
        }

        /// <summary>
        /// 获取Mono使用的内存大小
        /// </summary>
        /// <returns>Mono使用内存大小（以MB为单位）</returns>
        public static float GetMonoUsedMem()
        {
            var total = (float)UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong();
            total /= M_;
            return total;
        }

        /// <summary>
        /// 获取lua脚本作为资源占用的内存
        /// </summary>
        /// <returns>包含lua脚本数量和总内存大小的结果对象</returns>
        public static Result GetLuaSrcResMem()
        {
            Result r = new Result();
            r.count = luaSrcDict.Count;
            foreach (var i in luaSrcDict)
            {
                r.MB += i.Value;
            }
            return r;
        }

        /// <summary>
        /// 获取csv资源的内存使用
        /// </summary>
        /// <returns>包含csv资源数量和总内存大小的结果对象</returns>
        public static Result GetCSVResMem()
        {
            Result r = new Result();
            r.count = csvDict.Count;
            foreach (var i in csvDict)
            {
                r.MB += i.Value;
            }
            return r;
        }
    }
}